From: Alex Williamson Date: Thu, 27 Sep 2007 21:35:02 +0000 (-0600) Subject: [IA64] Kexec: partial port of CPU_HOTPLUG X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14945 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=d72c11579402a6ef4ec752a4ba9c353bd2394c0d;p=xen.git [IA64] Kexec: partial port of CPU_HOTPLUG * Enable CONFIG_CPU_HOTPLUG * Add #ifndef CONFIG_XEN as appropriate around portions that are not needed for kexec - it is used to take down cpus on SMP systems before kexecing. * Port various xen-specific bits as neccessary - This has mainly been done in the existing kexec-related files, as kexex is currently the only user of this code. If a full port of CPU_HOTPLUG was done then this code would either disapear or be relocated elsewhere. Signed-off-by: Simon Horman --- diff --git a/xen/arch/ia64/linux-xen/irq_ia64.c b/xen/arch/ia64/linux-xen/irq_ia64.c index d80cefdfef..29dde256f7 100644 --- a/xen/arch/ia64/linux-xen/irq_ia64.c +++ b/xen/arch/ia64/linux-xen/irq_ia64.c @@ -180,6 +180,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) irq_exit(); } +#ifndef XEN #ifdef CONFIG_HOTPLUG_CPU /* * This function emulates a interrupt processing when a cpu is about to be @@ -226,6 +227,7 @@ void ia64_process_pending_intr(void) irq_exit(); } #endif +#endif #ifdef CONFIG_SMP diff --git a/xen/arch/ia64/linux-xen/mca_asm.S b/xen/arch/ia64/linux-xen/mca_asm.S index a73a8e1daa..b5f95345df 100644 --- a/xen/arch/ia64/linux-xen/mca_asm.S +++ b/xen/arch/ia64/linux-xen/mca_asm.S @@ -147,8 +147,8 @@ #ifndef XEN .global ia64_sal_to_os_handoff_state .global ia64_os_to_sal_handoff_state - .global ia64_do_tlb_purge #endif + .global ia64_do_tlb_purge .text .align 16 diff --git a/xen/arch/ia64/linux-xen/process-linux-xen.c b/xen/arch/ia64/linux-xen/process-linux-xen.c index 5f04985cf9..ff71d80da8 100644 --- a/xen/arch/ia64/linux-xen/process-linux-xen.c +++ b/xen/arch/ia64/linux-xen/process-linux-xen.c @@ -6,6 +6,8 @@ * 04/11/17 Ashok Raj Added CPU Hotplug Support */ #ifdef XEN +#include +#include #include #include #include @@ -15,6 +17,7 @@ #include #include #include +#include #else #define __KERNEL_SYSCALLS__ /* see */ #include @@ -236,10 +239,15 @@ default_idle (void) else cpu_relax(); } +#endif #ifdef CONFIG_HOTPLUG_CPU /* We don't actually take CPU down, just spin without interrupts. */ +#ifndef XEN static inline void play_dead(void) +#else +void play_dead(void) +#endif { extern void ia64_cpu_local_tick (void); unsigned int this_cpu = smp_processor_id(); @@ -249,7 +257,6 @@ static inline void play_dead(void) max_xtp(); local_irq_disable(); - idle_domain_exit(); ia64_jump_to_sal(&sal_boot_rendez_state[this_cpu]); /* * The above is a point of no-return, the processor is @@ -258,12 +265,17 @@ static inline void play_dead(void) BUG(); } #else +#ifndef XEN static inline void play_dead(void) +#else +void play_dead(void) +#endif { BUG(); } #endif /* CONFIG_HOTPLUG_CPU */ +#ifndef XEN void cpu_idle_wait(void) { unsigned int cpu, this_cpu = get_cpu(); diff --git a/xen/arch/ia64/linux-xen/sal.c b/xen/arch/ia64/linux-xen/sal.c index 59cc613bbb..a0f19ed98b 100644 --- a/xen/arch/ia64/linux-xen/sal.c +++ b/xen/arch/ia64/linux-xen/sal.c @@ -129,7 +129,7 @@ sal_desc_entry_point (void *p) static void __init set_smp_redirect (int flag) { -#ifndef CONFIG_HOTPLUG_CPU +#if defined(CONFIG_HOTPLUG_CPU) && !defined(XEN) if (no_int_routing) smp_int_redirect &= ~flag; else diff --git a/xen/arch/ia64/linux-xen/smpboot.c b/xen/arch/ia64/linux-xen/smpboot.c index 6a48aaf1de..4a62ca9026 100644 --- a/xen/arch/ia64/linux-xen/smpboot.c +++ b/xen/arch/ia64/linux-xen/smpboot.c @@ -172,6 +172,27 @@ nointroute (char *str) __setup("nointroute", nointroute); +static void fix_b0_for_bsp(void) +{ +#ifdef CONFIG_HOTPLUG_CPU + int cpuid; + static int fix_bsp_b0 = 1; + + cpuid = smp_processor_id(); + + /* + * Cache the b0 value on the first AP that comes up + */ + if (!(fix_bsp_b0 && cpuid)) + return; + + sal_boot_rendez_state[0].br[0] = sal_boot_rendez_state[cpuid].br[0]; + printk ("Fixed BSP b0 value from CPU %d\n", cpuid); + + fix_bsp_b0 = 0; +#endif +} + void sync_master (void *arg) { @@ -358,6 +379,8 @@ smp_callin (void) BUG(); } + fix_b0_for_bsp(); + lock_ipi_calllock(); cpu_set(cpuid, cpu_online_map); unlock_ipi_calllock(); @@ -544,8 +567,10 @@ smp_build_cpu_map (void) for (cpu = 0; cpu < NR_CPUS; cpu++) { ia64_cpu_to_sapicid[cpu] = -1; +#ifndef XEN #ifdef CONFIG_HOTPLUG_CPU cpu_set(cpu, cpu_possible_map); +#endif #endif } @@ -626,7 +651,7 @@ static struct { __u8 valid; } mt_info[NR_CPUS] __devinitdata; -#ifdef CONFIG_HOTPLUG_CPU +#if defined(XEN) && !defined(CONFIG_HOTPLUG_CPU) static inline void remove_from_mtinfo(int cpu) { @@ -690,12 +715,21 @@ int __cpu_disable(void) remove_siblinginfo(cpu); cpu_clear(cpu, cpu_online_map); +#ifndef XEN fixup_irqs(); +#endif local_flush_tlb_all(); cpu_clear(cpu, cpu_callin_map); return 0; } +#else /* !CONFIG_HOTPLUG_CPU */ +int __cpu_disable(void) +{ + return -ENOSYS; +} +#endif /* CONFIG_HOTPLUG_CPU */ +#ifdef CONFIG_HOTPLUG_CPU void __cpu_die(unsigned int cpu) { unsigned int i; @@ -707,16 +741,17 @@ void __cpu_die(unsigned int cpu) printk ("CPU %d is now offline\n", cpu); return; } +#ifdef XEN + /* XXX: There must be a better way to sleep */ + for (int j = 0; j < 1000000; j++) + cpu_relax(); +#else msleep(100); +#endif } printk(KERN_ERR "CPU %u didn't die...\n", cpu); } #else /* !CONFIG_HOTPLUG_CPU */ -int __cpu_disable(void) -{ - return -ENOSYS; -} - void __cpu_die(unsigned int cpu) { /* We said "no" in __cpu_disable */ diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 73fcc83535..8da84f0bae 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -50,7 +50,10 @@ #include #include #include +#include #include +#include +#include /* dom0_size: default memory allocation for dom0 (~4GB) */ static unsigned long __initdata dom0_size = 4096UL*1024UL*1024UL; @@ -336,8 +339,12 @@ static void default_idle(void) local_irq_enable(); } +extern void play_dead(void); + static void continue_cpu_idle_loop(void) { + int cpu = smp_processor_id(); + for ( ; ; ) { #ifdef IA64 @@ -346,10 +353,12 @@ static void continue_cpu_idle_loop(void) irq_stat[cpu].idle_timestamp = jiffies; #endif page_scrub_schedule_work(); - while ( !softirq_pending(smp_processor_id()) ) + while ( !softirq_pending(cpu) ) default_idle(); raise_softirq(SCHEDULE_SOFTIRQ); do_softirq(); + if (!cpu_online(cpu)) + play_dead(); } } diff --git a/xen/arch/ia64/xen/machine_kexec.c b/xen/arch/ia64/xen/machine_kexec.c index 5cf49f21f8..c4f11ce8f9 100644 --- a/xen/arch/ia64/xen/machine_kexec.c +++ b/xen/arch/ia64/xen/machine_kexec.c @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)( unsigned long indirection_page, @@ -83,9 +86,68 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) BUG(); } -void machine_kexec(xen_kexec_image_t *image) +#if CONFIG_SMP +/* Need to implement some subset of hotplug-cpu - enough to + * send a cpu into rendevouz */ + +/* N.B: The tasks frozen parameter can probably be dropped + * This can probably be rolled into cpu_down + */ +static int _cpu_down(unsigned int cpu, int tasks_frozen) +{ + if (num_online_cpus() == 1) + return -EBUSY; + + if (!cpu_online(cpu)) + return -EINVAL; + +#ifndef XEN + /* XXX: What, if anything, should Xen do here? */ + /* Ensure that we are not runnable on dying cpu */ + old_affinity = current->cpus_allowed; + tmp = CPU_MASK_ALL; + cpu_clear(cpu, tmp); + set_cpus_allowed(current, tmp); +#endif + + cpu_clear(cpu, cpu_online_map); + + __cpu_die(cpu); + + return 0; +} + +static int cpu_down(unsigned int cpu) { + int err; + + /* Unlike Linux there is no lock, as there are no other callers + * and no other CPUS. */ + err = _cpu_down(cpu, 0); + + return 0; +} +#endif /* SMP */ + +/* This should probably be an arch-hook called from kexec_exec() + * Its also likely that it should be in the xen equivalent of + * arch/ia64/kernel/process.c */ +static void machine_shutdown(void) +{ +#ifdef CONFIG_SMP + unsigned int cpu; + + for_each_online_cpu(cpu) { + if (cpu != smp_processor_id()) + cpu_down(cpu); + } +#endif kexec_disable_iosapic(); +} + +void machine_kexec(xen_kexec_image_t *image) +{ + machine_shutdown(); unw_init_running(ia64_machine_kexec, image); for(;;); } diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 9120e1c723..6872d08dbe 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -24,6 +24,7 @@ #ifdef CONFIG_XEN_SMP #define CONFIG_SMP 1 +#define CONFIG_HOTPLUG_CPU 1 #define NR_CPUS 64 #define CONFIG_NUMA #define CONFIG_ACPI_NUMA diff --git a/xen/include/asm-ia64/linux-null/linux/cpu.h b/xen/include/asm-ia64/linux-null/linux/cpu.h deleted file mode 100644 index 29f4f4cd69..0000000000 --- a/xen/include/asm-ia64/linux-null/linux/cpu.h +++ /dev/null @@ -1 +0,0 @@ -/* This file is intentionally left empty. */ diff --git a/xen/include/asm-ia64/linux-xen/linux/README.origin b/xen/include/asm-ia64/linux-xen/linux/README.origin index 071d0648fc..7639720a9d 100644 --- a/xen/include/asm-ia64/linux-xen/linux/README.origin +++ b/xen/include/asm-ia64/linux-xen/linux/README.origin @@ -18,4 +18,5 @@ kobject.h -> linux/include/linux/kobject.h device.h -> linux/include/linux/device.h # The files below are from Linux-2.6.21 +cpu.h -> linux/include/linux/cpu.h efi.h -> linux/include/linux/efi.h diff --git a/xen/include/asm-ia64/linux-xen/linux/cpu.h b/xen/include/asm-ia64/linux-xen/linux/cpu.h new file mode 100644 index 0000000000..2d0a8b76d9 --- /dev/null +++ b/xen/include/asm-ia64/linux-xen/linux/cpu.h @@ -0,0 +1,26 @@ +#ifndef _ASM_IA64_CPU_H_ +#define _ASM_IA64_CPU_H_ + +#include +#include +#include +#include + +#ifndef XEN +struct ia64_cpu { + struct cpu cpu; +}; + +DECLARE_PER_CPU(struct ia64_cpu, cpu_devices); +#endif + +DECLARE_PER_CPU(int, cpu_state); + +#ifndef XEN +extern int arch_register_cpu(int num); +#ifdef CONFIG_HOTPLUG_CPU +extern void arch_unregister_cpu(int); +#endif +#endif + +#endif /* _ASM_IA64_CPU_H_ */